package com.zjj.crypt.advice;


import cn.hutool.core.codec.Base64;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONConverter;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zjj.crypt.anno.ZjjEncryptResponse;
import com.zjj.crypt.constant.AlgorithmType;
import com.zjj.crypt.util.ConvertHelper;
import com.zjj.crypt.util.CryptUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * 对使用了 EncryptResponse 的方法或者类的返回数据进行加密
 *
 * @author zjj_admin
 * @date 2023/4/23 10:30
 */
@RestControllerAdvice
public class EncryptResponseBodyAdvice implements ResponseBodyAdvice<Object> {

    @Value("${com.zjj.crypt.DES.KEY}")
    private String DES_KRY = "";

    @Value("${com.zjj.crypt.DES_3.KEY}")
    private String DES_3_KRY = "";

    @Value("${com.zjj.crypt.AES.KEY}")
    private String AES_KRY = "";

    @Value("${com.zjj.crypt.RSA.PUBLIC_KEY}")
    private String RSA_PUBLIC_KEY = "";

    @Value("${com.zjj.crypt.RSA.PRIVATE_KEY}")
    private String RSA_PRIVATE_KEY = "";

    /**
     * 判断当前的请求在返回结果之前是否需要执行 beforeBodyWrite 方法中的操作
     *
     * @param returnType
     * @param converterType
     * @return
     */
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return NeedCrypt.isNeedEncrypt(returnType);
    }

    /**
     * 结果返回之前执行
     *
     * @param body
     * @param methodParameter
     * @param mediaType
     * @param selectedConverterType
     * @param request
     * @param response
     * @return 将数据转化成字符串后，加密返回结果
     */
    @Override
    public Object beforeBodyWrite(Object body,
                                  MethodParameter methodParameter,
                                  MediaType mediaType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        //首先将返货结果转化成JSON字符串
        String data = JSONUtil.toJsonStr(body);
        String res = null;
        ZjjEncryptResponse encryptResponse = methodParameter.getMethod().getAnnotation(ZjjEncryptResponse.class);
        AlgorithmType type = encryptResponse.type();
        switch (type) {
            case DES:
                res = CryptUtil.encryptDES(data, DES_KRY);
                break;
            case AES:
                res = CryptUtil.encryptAES(data, AES_KRY);
                break;
            case DES_3:
                res = CryptUtil.encryptDES_3(data, DES_3_KRY);
                break;
            case MD5:
                res = CryptUtil.encryptMd5(data);
                break;
            case Base64:
                res = Base64.encode(data);
                break;
            case RSA:
                res = CryptUtil.encryptRSA(data, RSA_PUBLIC_KEY);
                break;
            default:
        }
        return res;
    }
}
